package com.zsk.shop.service;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.zsk.shop.common.base.BaseResponse;
import com.zsk.shop.common.enums.EnumQRCodeType;
import com.zsk.shop.common.utils.*;
import com.zsk.shop.entity.ShopUser;
import com.zsk.shop.enums.EnumDecodeClientType;
import com.zsk.shop.model.results.AppUserDecodeResult;
import com.zsk.shop.model.results.WeChatDecodeUserResult;
import com.zsk.shop.model.wechatDecode.AppUserWXParam;
import com.zsk.shop.model.wechatDecode.WeiXinToken;
import com.zsk.shop.api.pay.common.util.str.StringUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static com.alipay.api.AlipayConstants.ACCESS_TOKEN;

/**
 * <p>
 * 微信授权
 * </p>
 *
 * @author lvjunhua
 * @since 2019-03-08
 */
@Service
public class WxDecodeService {

    private static final Logger logger = LoggerFactory.getLogger(WxDecodeService.class);

    @Resource
    private Environment environment;
    @Resource
    private ShopUserService shopUserService;
    @Autowired
    private BaseService baseService;

    private static final String ACCESS_TOKEN = "accessToken";
    private static final String OPENID = "openid";

    public BaseResponse getJsApiTicket(String url) {
        Map<String, Object> map = new HashMap<>();
        JSONObject json = null;
        try {
            String wxTicket = (String) RedisUtil.get("wx:ticket:" + url);
            if (ToolUtil.isNotEmpty(wxTicket) && wxTicket.length() > 10) {
                Map<String, Object> keyValue = new Gson().fromJson(wxTicket, Map.class);
                logger.info(keyValue + "---------------------");
                return BaseResponse.success(keyValue);
            } else {
                String str = URLDecoder.decode(url, "utf-8");
                String params = "grant_type=client_credential&appid=" + environment.getProperty("weChat.jsAppId")
                        + "&secret=" + environment.getProperty("weChat.jsAppSecret");
                String info = HttpUtil.sendGet("https://api.weixin.qq.com/cgi-bin/token", params);
                json = JSONObject.parseObject(info);
                String accessToken = json.get("access_token").toString();
                if (ToolUtil.isNotEmpty(accessToken)) {
                    String getTicket = "access_token=" + accessToken + "&type=jsapi";
                    String obj = HttpUtil.sendGet("https://api.weixin.qq.com/cgi-bin/ticket/getticket", getTicket);
                    JSONObject jsonObj = JSONObject.parseObject(obj);
                    logger.info("获取jsapi_ticket:" + json);
                    String jsapi_ticket = jsonObj.get("ticket").toString();
                    String noncestr = UUID.randomUUID().toString();
                    Long timestamp = System.currentTimeMillis() / 1000;
                    String ps = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + str;
                    String signature = DigestUtils.sha1Hex(StringUtils.getContentBytes(ps, "utf-8"));
                    map.put("appId", environment.getProperty("weChat.jsAppId"));
                    map.put("timestamp", timestamp);
                    map.put("nonceStr", noncestr);
                    map.put("signature", signature);
                    String value = new Gson().toJson(map);
                    RedisUtil.setForTimeS("wx:ticket:" + url, value, 6000);
                    return BaseResponse.success(map);
                }
            }
        } catch (Exception e) {
            logger.info(e + "---------------------");
            return BaseResponse.error("签名验证失败");
        }
        return BaseResponse.error("签名验证失败");
    }

    /**
     * 公众号授权
     *
     * @param code
     * @return token
     */
    public BaseResponse<AppUserDecodeResult> wxJsDecode(String code) {
        String jsAppId = environment.getProperty("weChat.jsAppId");
        String jsAppSecret = environment.getProperty("weChat.jsAppSecret");
        WeiXinToken oauth2AccessToken = WeiXinUtil.getOauth2AccessToken(jsAppId, jsAppSecret, code);
        WeChatDecodeUserResult weiXinUserInfo = WeiXinUtil.getUserInfo(oauth2AccessToken.getAccessToken(),
                oauth2AccessToken.getOpenId());
        AppUserWXParam param = new AppUserWXParam();
        param.setWxName(weiXinUserInfo.getNickname());
        param.setWxAvatar(weiXinUserInfo.getHeadimgurl());
        param.setGender(weiXinUserInfo.getSex());
        param.setWxJsOpenId(weiXinUserInfo.getOpenid());
        param.setUnionId(weiXinUserInfo.getUnionid());
        ShopUser user = shopUserService.loginWeChat(param);
        if (ToolUtil.isOneEmpty(user, user.getUserNo())) {
            return BaseResponse.error("微信授权登录出现错误");
        }
        return BaseResponse.success("微信公众号登录成功", baseService.getDecodeResult(user));
    }

    /**
     * code 获取 access_token
     *
     * @param code
     * @return
     */
    public BaseResponse<AppUserDecodeResult> wxDecode(String code) {
        System.out.println(environment.getProperty("weChat.appId"));
        Map<String, String> map = getAccessToken(code, environment.getProperty("weChat.appId"), environment.getProperty("weChat.appSecret"));
        if (ToolUtil.isOneEmpty(map.get(ACCESS_TOKEN), map.get(OPENID))) {
            return BaseResponse.error("授权信息获取失败");
        }
        WeChatDecodeUserResult userResult = getUserInfo(map.get(ACCESS_TOKEN), map.get(OPENID));
        if (ToolUtil.isNotEmpty(userResult)) {
            AppUserWXParam param = new AppUserWXParam();
            param.setWxName(userResult.getNickname());
            param.setWxAvatar(userResult.getHeadimgurl());
            param.setGender(userResult.getSex());
            param.setWxOpenId(userResult.getOpenid());
            param.setUnionId(userResult.getUnionid());
            ShopUser user = shopUserService.loginWeChat(param);
            if (ToolUtil.isOneEmpty(user, user.getUserNo())) {
                return BaseResponse.error("微信授权登录出现错误");
            }
            return BaseResponse.success("微信授权登录成功", baseService.getDecodeResult(user));
        }
        return new BaseResponse(BaseResponse.FAIL, "微信给与用户信息数据出错", null);
    }

    private Map<String, String> getAccessToken(String code, String appid, String secret) {
        Map<String, String> map = new HashedMap();
        map.put(ACCESS_TOKEN, "");
        map.put(OPENID, "");
        String grantType = "authorization_code";
        // 请求参数
        String params = "appid=" + appid + "&secret=" + secret + "&code=" + code + "&grant_type=" + grantType;
        // 发送请求
        String sr = HttpUtil.sendGet("https://api.weixin.qq.com/sns/oauth2/access_token", params);
        //{"errcode":41008,"errmsg":"missing code rid: 6062d385-433dfbcd-179fd304"}
//        {
//            "access_token": "ACCESS_TOKEN",
//                "expires_in": 7200,
//                "refresh_token": "REFRESH_TOKEN",
//                "openid": "OPENID",
//                "scope": "SCOPE",
//                "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
//        }
        // 解析相应内容（转换成json对象）
        JSONObject json = JSONObject.parseObject(sr);
        logger.info("是否包含了用户基础信息:" + json);
        if (json.containsKey("errcode")) {
            String errcode = json.get("errcode").toString();
            String errmsg = json.get("errmsg").toString();
            logger.error("得到session_key时解密失败" + errcode + ":" + errmsg);
        }
        try {
            // 获取会话密钥（session_key）
            String access_token = json.get("access_token").toString();
            String openid = json.get("openid").toString();
            map.put(ACCESS_TOKEN, access_token);
            map.put(OPENID, openid);
        } catch (Exception e) {
            logger.warn(e.getMessage());
        }
        return map;
    }

    /**
     * 通过code 获取用户微信数据
     *
     * @param type
     * @param code
     * @return
     */
    public WeChatDecodeUserResult getUserInfo(Integer type, String code) {
        String appId = "";
        String appSecret = "";
        if (type.equals(EnumDecodeClientType.CLIENT.getCode())) {
            appId = environment.getProperty("weChat.appId");
            appSecret = environment.getProperty("weChat.appSecret");
        } else if (type.equals(EnumDecodeClientType.H5.getCode())) {
            appId = environment.getProperty("weChat.h5AppId");
            appSecret = environment.getProperty("weChat.h5AppSecret");
        } else if (type.equals(EnumDecodeClientType.JS.getCode())) {
            appId = environment.getProperty("weChat.jsAppId");
            appSecret = environment.getProperty("weChat.jsAppSecret");
        } else if (type.equals(EnumDecodeClientType.MINI.getCode())) {
            appId = environment.getProperty("weChat.miniAppId");
            appSecret = environment.getProperty("weChat.miniAppSecret");
        }
        WeiXinToken oauth2AccessToken = WeiXinUtil.getOauth2AccessToken(appId, appSecret, code);
        WeChatDecodeUserResult weiXinUserInfo = WeiXinUtil.getUserInfo(oauth2AccessToken.getAccessToken(),
                oauth2AccessToken.getOpenId());
        if (ToolUtil.isEmpty(weiXinUserInfo)) {
            return null;
        }
        return weiXinUserInfo;
    }

    private WeChatDecodeUserResult getUserInfo(String accessToken, String openid) {
        // 请求参数
        String params = "access_token=" + accessToken + "&openid=" + openid;
        // 发送请求
        String sr = HttpUtil.sendGet("https://api.weixin.qq.com/sns/userinfo", params);
        //{"openid":"oPIEF6qIlCHrhduNDj-0lQJyLBiQ","nickname":"郝晓辉","sex":0,"language":"zh_CN","city":"Ningbo","province":"Zhejiang","country":"CN","headimgurl":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/IXht1aItKN4V15HeLHuECsB2vJ4lU79daOGMEHqyssuSQRTyPeuZf5eexlenrW0uCdpIpRJpna3jeoqDIfEOpA\/132","privilege":[],"unionid":"o0CWK5zivqV66tTbDsmaiwjnX6Yg"}
        // 解析相应内容（转换成json对象）
        JSONObject json = JSONObject.parseObject(sr);
        logger.info("请求用户的用户信息结果返回（为了性别头像还是得获取下，尽管OPENID是一致的）:" + json);
        if (json.containsKey("errcode")) {
            String errcode = json.get("errcode").toString();
            String errmsg = json.get("errmsg").toString();
            logger.error("得到session_key时解密失败" + errcode + ":" + errmsg);
        }
        WeChatDecodeUserResult result = null;
        try {
            result = JSONObject.parseObject(sr, WeChatDecodeUserResult.class);
        } catch (Exception e) {
            logger.warn(e.getMessage());
        }
        return result;
    }
}
